package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.DaoAccountBankInfoDao;
import com.sc.nft.dao.DaoAccountLegalPersonDao;
import com.sc.nft.dao.DaoCustomerOpenAccountDao;
import com.sc.nft.dao.UserCreatorInfoDao;
import com.sc.nft.dto.wallet.DaoAccountDTO;
import com.sc.nft.dto.wallet.DaoLegalPersonDTO;
import com.sc.nft.dto.wallet.DaoOpenWalletDTO;
import com.sc.nft.dto.wallet.VerifyOpenAccountDTO;
import com.sc.nft.entity.DaoAccountBankInfo;
import com.sc.nft.entity.DaoAccountLegalPerson;
import com.sc.nft.entity.DaoCustomerOpenAccount;
import com.sc.nft.entity.UserCreatorInfo;
import com.sc.nft.entity.dto.DaoUnbindDTO;
import com.sc.nft.enums.AccountStatusEnum;
import com.sc.nft.enums.WalletChannelEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.service.DaoCustomerOpenAccountService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * 服务接口实现
 *
 * @author zxy
 * @description 商户banner
 * @since 2023-11-25 16:18:38
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DaoCustomerOpenAccountServiceImpl implements DaoCustomerOpenAccountService {
    private final DaoCustomerOpenAccountDao customerOpenAccountDao;
    private final DaoAccountBankInfoDao accountBankInfoDao;
    private final DaoAccountLegalPersonDao accountLegalPersonDao;
    private final UserCreatorInfoDao userCreatorInfoDao;
    private final LlPayHelper llPayHelper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customerOpenAccount(DaoOpenWalletDTO dto) {

        UserCreatorInfo userCreatorInfo = userCreatorInfoDao.getById(dto.getDaoId());
        if (userCreatorInfo.getStatus().intValue() == 0) {
            throw new GlobalRunTimeException("当前组织不是DAO");
        }
        DaoCustomerOpenAccount customerOpenAccount = customerOpenAccountDao.getByChannel(dto.getDaoId(), WalletChannelEnum.LL);
        if (ObjectUtil.isNotNull(customerOpenAccount)) {
            Assert.isFalse(customerOpenAccount.getStatus() == AccountStatusEnum.OPENING, () -> new GlobalRunTimeException("当前账户正在开户中，请耐心等待"));
            Assert.isFalse(customerOpenAccount.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("您已完成开户，无需再次申请"));
        } else {
            customerOpenAccount = new DaoCustomerOpenAccount();
            customerOpenAccount.setDaoUuid(userCreatorInfo.getDaoUuid());
            customerOpenAccount.setCreateId(dto.getOperatorId());
            customerOpenAccount.setCreateTime(DateTime.now());
        }
        customerOpenAccount.setDaoId(dto.getDaoId());
        customerOpenAccount.setChannel(WalletChannelEnum.LL);
        customerOpenAccount.setSeqNo(UUID.fastUUID().toString().replaceAll("-", ""));
        customerOpenAccount.setRegPhone(dto.getRegPhone());
        customerOpenAccount.setBusinessName(dto.getBusinessName());
        customerOpenAccount.setBusinessLicenseCode(dto.getBusinessLicenseCode());
        customerOpenAccount.setBusinessLicenseImage(dto.getBusinessLicenseImage());
        customerOpenAccount.setExpDate(dto.getExpDate());
        customerOpenAccount.setAddress(dto.getAddress());
        customerOpenAccount.setRegMail(dto.getRegEmail());
        customerOpenAccount.setContactsName(dto.getContactsName());
        customerOpenAccount.setContactsPhone(dto.getContactsPhone());
        customerOpenAccount.setStatus(AccountStatusEnum.OPENING);
        customerOpenAccount.setOperatorId(dto.getOperatorId());
        customerOpenAccount.insertOrUpdate();
        accountBankInfoDao.clearByAccountId(customerOpenAccount.getId());
        DaoAccountBankInfo daoAccountBankInfo = new DaoAccountBankInfo();
        daoAccountBankInfo.setDaoId(dto.getDaoId());
        daoAccountBankInfo.setDaoOpenAccountId(customerOpenAccount.getId());
        daoAccountBankInfo.setBankAccount(dto.getAccountDTO().getBankAccount());
        daoAccountBankInfo.setBankName(dto.getAccountDTO().getBankName());
        daoAccountBankInfo.setBankCode(dto.getAccountDTO().getBankCode());
        daoAccountBankInfo.setBrBankName(dto.getAccountDTO().getBrBankName());
        daoAccountBankInfo.setBrBankCode(dto.getAccountDTO().getBrBankCode());
        daoAccountBankInfo.setProvince(dto.getAccountDTO().getProvince());
        daoAccountBankInfo.setProvinceCode(dto.getAccountDTO().getProvinceCode());
        daoAccountBankInfo.setCity(dto.getAccountDTO().getCity());
        daoAccountBankInfo.setCityCode(dto.getAccountDTO().getCityCode());
        daoAccountBankInfo.setPhone(dto.getAccountDTO().getPhone());
        daoAccountBankInfo.insert();
        accountLegalPersonDao.clearByAccountId(customerOpenAccount.getId());
        DaoAccountLegalPerson accountLegalPerson = new DaoAccountLegalPerson();
        accountLegalPerson.setDaoOpenAccountId(customerOpenAccount.getId());
        accountLegalPerson.setDaoId(customerOpenAccount.getDaoId());
        accountLegalPerson.setLegalPersonName(dto.getLegalPersonDTO().getLegalPersonName());
        accountLegalPerson.setLegalPersonPhone(dto.getLegalPersonDTO().getLegalPersonPhone());
        accountLegalPerson.setLegalPersonIdCard(dto.getLegalPersonDTO().getLegalPersonIdCard());
        accountLegalPerson.setLegalPersonEmblem(dto.getLegalPersonDTO().getLegalPersonEmblem());
        accountLegalPerson.setLegalPersonPortrait(dto.getLegalPersonDTO().getLegalPersonPortrait());
        accountLegalPerson.setLegalPersonExp(dto.getLegalPersonDTO().getLegalPersonExp());
        accountLegalPerson.insert();
        JSONObject result = null;
        result = llPayHelper.businessOpenAccount(customerOpenAccount, accountLegalPerson, daoAccountBankInfo, dto.getPassword(), dto.getRandomKey());
        customerOpenAccount.setReqToken(result.getString("token"));
        customerOpenAccount.setAccpTxNo(result.getString("accp_txno"));
        customerOpenAccount.setOidUserNo(result.getString("oid_userno"));
        customerOpenAccount.setModifyId(customerOpenAccount.getOperatorId());
        customerOpenAccount.setModifyTime(DateTime.now());
        customerOpenAccount.updateById();
    }

    @Override
    public void verifyOpenAccount(VerifyOpenAccountDTO dto) {
        DaoCustomerOpenAccount customerOpenAccount = customerOpenAccountDao.getById(dto.getId());
        Assert.notNull(customerOpenAccount, () -> new GlobalRunTimeException("未找到开户记录"));
        Assert.isTrue(customerOpenAccount.getDaoId().longValue() == dto.getDaoId().longValue(), () -> new GlobalRunTimeException("未找到开户记录"));
        Assert.isFalse(customerOpenAccount.getStatus() == AccountStatusEnum.OPENING, () -> new GlobalRunTimeException("您已提交过开户申请，请耐心等待"));
        Assert.isFalse(customerOpenAccount.getStatus() == AccountStatusEnum.SUCCESS, () -> new GlobalRunTimeException("开户已完成，请不要重复提交"));
        Assert.isFalse(customerOpenAccount.getStatus() == AccountStatusEnum.FAIl, () -> new GlobalRunTimeException("开户失败，请修改资料后重新提交"));
        llPayHelper.openAccountVerify(customerOpenAccount.getOperatorId(), customerOpenAccount.getDaoUuid(), customerOpenAccount.getSeqNo(), customerOpenAccount.getReqToken(), dto.getVerifyCode());
        customerOpenAccount.setStatus(AccountStatusEnum.OPENING);
        customerOpenAccount.updateById();
    }

    @Override
    public DaoOpenWalletDTO getByIdAndDaoId(Long id, Long daoId) {
        DaoCustomerOpenAccount customerOpenAccount = customerOpenAccountDao.getById(id);
        Assert.isTrue(ObjectUtil.isNotNull(customerOpenAccount) && customerOpenAccount.getDaoId().longValue() == daoId.longValue(), () -> new GlobalRunTimeException("未找到钱包开户记录"));
        DaoOpenWalletDTO dto = new DaoOpenWalletDTO();
        if (ObjectUtil.isNull(customerOpenAccount)) {
            dto.setAccountDTO(new DaoAccountDTO());
            dto.setLegalPersonDTO(new DaoLegalPersonDTO());
        } else {
            dto.setDaoId(customerOpenAccount.getDaoId());
            dto.setOperatorId(customerOpenAccount.getOperatorId());
            dto.setRegPhone(customerOpenAccount.getRegPhone());
            dto.setBusinessName(customerOpenAccount.getBusinessName());
            dto.setBusinessLicenseCode(customerOpenAccount.getBusinessLicenseCode());
            dto.setExpDate(customerOpenAccount.getExpDate());
            dto.setBusinessLicenseImage(customerOpenAccount.getBusinessLicenseImage());
            dto.setAddress(customerOpenAccount.getAddress());
            dto.setRegEmail(customerOpenAccount.getRegMail());
            DaoAccountBankInfo accountBankInfo = accountBankInfoDao.getByAccountId(customerOpenAccount.getId());
            DaoAccountDTO accountDTO = new DaoAccountDTO();
            accountDTO.setBankAccount(accountBankInfo.getBankAccount());
            accountDTO.setBankName(accountBankInfo.getBankName());
            accountDTO.setBankCode(accountBankInfo.getBankCode());
            accountDTO.setBrBankName(accountBankInfo.getBrBankName());
            accountDTO.setProvince(accountBankInfo.getProvince());
            accountDTO.setProvinceCode(accountBankInfo.getProvinceCode());
            accountDTO.setCity(accountBankInfo.getCity());
            accountDTO.setCityCode(accountBankInfo.getCityCode());
            accountDTO.setBrBankCode(accountBankInfo.getBrBankCode());
            accountDTO.setPhone(accountBankInfo.getPhone());
            dto.setAccountDTO(accountDTO);

            DaoAccountLegalPerson legalPerson = accountLegalPersonDao.getByAccountId(customerOpenAccount.getId());
            DaoLegalPersonDTO daoLegalPersonDTO = new DaoLegalPersonDTO();
            daoLegalPersonDTO.setLegalPersonName(legalPerson.getLegalPersonName());
            daoLegalPersonDTO.setLegalPersonPhone(legalPerson.getLegalPersonPhone());
            daoLegalPersonDTO.setLegalPersonIdCard(legalPerson.getLegalPersonIdCard());
            daoLegalPersonDTO.setLegalPersonEmblem(legalPerson.getLegalPersonEmblem());
            daoLegalPersonDTO.setLegalPersonPortrait(legalPerson.getLegalPersonPortrait());
            daoLegalPersonDTO.setLegalPersonExp(legalPerson.getLegalPersonExp());
            dto.setLegalPersonDTO(daoLegalPersonDTO);
            dto.setContactsName(customerOpenAccount.getContactsName());
            dto.setContactsPhone(customerOpenAccount.getContactsPhone());
        }
        return dto;
    }

    @Override
    public Page<DaoCustomerOpenAccount> getByDaoId(Long daoId, WalletChannelEnum walletChannel, Page page) {
        return customerOpenAccountDao.getByDaoId(daoId, walletChannel, page);
    }

    @Override
    public Page<DaoAccountBankInfo> getWalletBankCardPage(Long id, Long daoId, Page page) {
        return accountBankInfoDao.getByDaoAndAccountId(id, daoId, page);
    }
    @Override
    public void unbind(DaoUnbindDTO dto) {
        DaoCustomerOpenAccount daoCustomerOpenAccount = customerOpenAccountDao.getByDaoIdAndId(dto.getDaoId(),dto.getId());
        if (BeanUtil.isEmpty(daoCustomerOpenAccount)) {
            throw new GlobalRunTimeException("未找到开户记录");
        }
        if (daoCustomerOpenAccount.getStatus() == AccountStatusEnum.SUCCESS) {
            // 必须是开户成功的才可以解绑
            // 逻辑删除这一条数据,删除之前先验证第三方里面有没有余额
            BigDecimal amtBalaval = llPayHelper.getDaoBalance(daoCustomerOpenAccount.getOperatorId(), daoCustomerOpenAccount.getDaoUuid()).getBigDecimal("amt_balaval");
            if (amtBalaval.compareTo(BigDecimal.ZERO) > 0) {
                throw new GlobalRunTimeException("当前账户还有余额，请先提现");
            }
            // 逻辑删除
            daoCustomerOpenAccount.deleteById();
            userCreatorInfoDao.updateDaoUUId(dto.getDaoId());
        } else {
            throw new GlobalRunTimeException("只有开户成功才可以解绑");
        }
    }
}